home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #4 / Amiga Plus CD - 2000 - No. 4.iso / Tools / Musik / Misc / Amster / Source / thread.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-27  |  4.2 KB  |  265 lines

  1. /*
  2. ** Threading Functions
  3. */
  4.  
  5. #include "include/config.h"
  6.  
  7. #include <stdlib.h>
  8. #include <string.h>
  9.  
  10. #include <proto/exec.h>
  11. #include <proto/dos.h>
  12. #include <dos/dostags.h>
  13.  
  14. #include "include/thread.h"
  15.  
  16. struct MsgPort *th_mother=NULL;
  17. thread th_list=NULL;
  18. u_long th_sigmask=0;
  19.  
  20. void th_handlemsg(thmsg m);
  21. void th_cleanup(thread t);
  22.  
  23.  
  24. int th_lala(void)
  25. {
  26.     th_mother = CreateMsgPort();
  27.     if (!th_mother) return(0);
  28.     th_sigmask = 1L << (th_mother->mp_SigBit);
  29.     return(1);
  30. }
  31.  
  32.  
  33. void th_bibi(void)
  34. {
  35.     thread t;
  36.  
  37.     t = th_list;
  38.     while (t) {
  39.         th_message(t,THC_EXIT,0);
  40.         t = t->next;
  41.     }
  42.  
  43.     while (th_list) {
  44.         thmsg m;
  45.         WaitPort(th_mother);
  46.         m = (thmsg)GetMsg(th_mother);
  47.         th_handlemsg(m);
  48.     }
  49.  
  50.     DeleteMsgPort(th_mother);
  51.     th_sigmask = 0;
  52. }
  53.  
  54.  
  55. thread th_spawn(thcb handler, char *name, void (*func)(void), int pri, APTR data)
  56. {
  57.     thread t;
  58.  
  59.     t = malloc(sizeof(_thread));
  60.     if (!t) return(NULL);
  61.     memset(t,0,sizeof(_thread));
  62.  
  63.     t->task = (struct Task *)CreateNewProcTags(
  64.         NP_Entry, func,
  65.         NP_Name, name,
  66.         NP_StackSize, 8192,
  67.         NP_Priority, pri,
  68.         TAG_DONE);
  69.  
  70.     if (!t->task) {
  71.         free(t);
  72.         return(NULL);
  73.     }
  74.  
  75.     t->handler = handler;
  76.     t->mother = th_mother;
  77.     t->data = data;
  78.  
  79.     t->sm.header.mn_ReplyPort = th_mother;
  80.     t->sm.header.mn_Length = sizeof(_thmsg);
  81.     t->sm.com = THC_STARTUP;
  82.     t->sm.data = t;
  83.  
  84.     /* Begin new stuff */
  85.     t->task->tc_UserData = &t->sm;
  86.     t->mother_task = FindTask(NULL);
  87.     SetSignal(0L, SIGF_SINGLE);
  88.     Signal(t->task, SIGF_SINGLE);
  89.     Wait(SIGF_SINGLE);
  90.     /* End new stuff */
  91.  
  92.     /* Old stuff
  93.     PutMsg(&((struct Process *)t->task)->pr_MsgPort,(struct Message *)&t->sm);
  94.        End old stuff */
  95.  
  96.     /* Begin new stuff */
  97.     if(handler)    (handler)(t,THC_STARTUP,data);
  98.     /* End new stuff */
  99.  
  100.     t->next = th_list;
  101.     th_list = t;
  102.     return(t);
  103. }
  104.  
  105.  
  106. void th_message(thread t, int com, APTR data)
  107. {
  108.     thmsg m;
  109.  
  110.     if(!t) return;
  111.     if(!t->port) return;
  112.  
  113.     m = malloc(sizeof(_thmsg));
  114.     if(!m) return;
  115.     memset(m,0,sizeof(_thmsg));
  116.  
  117.     m->header.mn_ReplyPort = th_mother;
  118.     m->header.mn_Length = sizeof(_thmsg);
  119.     m->com = com;
  120.     m->data = data;
  121.  
  122.     PutMsg(t->port,(struct Message *)m);
  123. }
  124.  
  125.  
  126. void th_poll(void)
  127. {
  128.     thread t;
  129.     thmsg m;
  130.  
  131.     while(1) {
  132.         m = (thmsg)GetMsg(th_mother);
  133.         if(!m) break;
  134.  
  135.         if(m->com != THC_FINISH && (!m->isreply)) {
  136.             t = m->sender;
  137.             if(t && t->handler)
  138.                 (t->handler)(t,m->com,m->data);
  139.         }
  140.  
  141.         th_handlemsg(m);
  142.     }
  143. }
  144.  
  145.  
  146. thread thr_init(void)
  147. {
  148.     thread t;
  149.     thmsg m;
  150.     struct Task *me = FindTask(NULL);
  151.  
  152.     /* Begin new stuff */
  153.     Wait(SIGF_SINGLE);
  154.     m = (thmsg)me->tc_UserData;
  155.     t = (thread)m->data;
  156.  
  157.     t->port = CreateMsgPort();
  158.     if(!t->port) {
  159.         me->tc_UserData = (APTR)FALSE;
  160.         t = NULL;
  161.     }
  162.     else {
  163.         me->tc_UserData = (APTR)TRUE;
  164.         m->sender = t;
  165.     }
  166.     Signal(t->mother_task, SIGF_SINGLE);
  167.     /* End new stuff */
  168.  
  169.     /* Begin old stuff
  170.     WaitPort(&((struct Process *)me)->pr_MsgPort);
  171.     m = (thmsg)GetMsg(&((struct Process *)me)->pr_MsgPort);
  172.     t = m->data;
  173.  
  174.     t->port = CreateMsgPort();
  175.     if(!t->port) return(NULL);
  176.  
  177.     m->sender = t;
  178.     ReplyMsg((struct Message *)m);
  179.        End old stuff */
  180.  
  181.     return(t);
  182. }
  183.  
  184.  
  185. void thr_exit(thread t, int reason)
  186. {
  187.     t->em.header.mn_ReplyPort = t->port;
  188.     t->em.header.mn_Length = sizeof(_thmsg);
  189.     t->em.com = THC_EXIT;
  190.     t->em.data = (APTR)reason;
  191.     t->em.sender = t;
  192.     PutMsg(t->mother,(struct Message *)&t->em);
  193.  
  194.     while(1) {
  195.         thmsg m;
  196.         WaitPort(t->port);
  197.         m = (thmsg)GetMsg(t->port);
  198.         if(&t->em == m) break;
  199.         m->isreply = 1;
  200.         ReplyMsg((struct Message *)m);
  201.     }
  202.  
  203.     Forbid();
  204.     t->em.sender = t;
  205.     t->em.com = THC_FINISH;
  206.     PutMsg(t->mother,(struct Message *)&t->em);
  207.  
  208.     if(t->port) DeleteMsgPort(t->port);
  209. }
  210.  
  211.  
  212. void thr_message(thread t, int com, APTR data)
  213. {
  214.     thmsg m;
  215.  
  216.     m = malloc(sizeof(_thmsg));
  217.     if(!m) return;
  218.     memset(m,0,sizeof(_thmsg));
  219.  
  220.     m->header.mn_ReplyPort = t->port;
  221.     m->header.mn_Length = sizeof(_thmsg);
  222.     m->sender = t;
  223.     m->com = com;
  224.     m->data = data;
  225.  
  226.     PutMsg(t->mother,(struct Message *)m);
  227. }
  228.  
  229.  
  230. /* private functions */
  231.  
  232. void th_handlemsg(thmsg m)
  233. {
  234.     if(m->com==THC_STARTUP) return;
  235.  
  236.     if(m->com==THC_FINISH) {
  237.         th_cleanup(m->sender);
  238.     } else {
  239.         if(m->isreply) {
  240.             free(m);
  241.         } else {
  242.             m->isreply = 1;
  243.             ReplyMsg((struct Message *)m);
  244.         }
  245.     }
  246. }
  247.  
  248.  
  249. void th_cleanup(thread t)
  250. {
  251.     if(th_list==t) {
  252.         th_list = t->next;
  253.     } else {
  254.         thread tmp = th_list;
  255.         while(tmp) {
  256.             if(tmp->next==t) {
  257.                 tmp->next=t->next;
  258.                 break;
  259.             }
  260.             tmp = tmp->next;
  261.         }
  262.     }
  263.     free(t);
  264. }
  265.